package com.example.course.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.course.bean.Classes;
import com.example.course.bean.Student;
import com.example.course.converter.StudentConverter;
import com.example.course.dto.LoginDTO;
import com.example.course.dto.StudentDTO;
import com.example.course.dto.StudentQueryDTO;
import com.example.course.dto.StudentUpdateDTO;
import com.example.course.mapper.StudentMapper;
import com.example.course.service.ClassesService;
import com.example.course.service.StudentService;
import com.example.course.tool.BCryptUtil;
import com.example.course.vo.LoginVO;
import com.example.course.vo.StudentVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * @author Jasmine-drs
 * @description 针对表【student(学生表)】的数据库操作Service实现
 * @createDate 2025-04-22 15:36:40
 */
@Service
@Slf4j
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student>
		implements StudentService {

	private final ClassesService classesService;
	private final StudentConverter studentConverter;
	private final BCryptUtil bCryptUtil;

	public StudentServiceImpl(@Lazy ClassesService classesService, StudentConverter studentConverter, BCryptUtil bCryptUtil) {
		this.classesService = classesService;
		this.studentConverter = studentConverter;
		this.bCryptUtil = bCryptUtil;
	}

	/**
	 * 获取学生列表，支持按条件查询和分页
	 *
	 * @param queryDTO 查询条件
	 * @return 学生分页列表
	 */
	@Override
	public Page<StudentVO> getStudentList(StudentQueryDTO queryDTO) {
		log.info("执行查询学生列表：{}", queryDTO);

		// 构建分页对象
        Page<Student> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());

        // 构建查询条件
        LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();

        // 姓名模糊查询
        if (!StringUtils.isEmpty(queryDTO.getName())) {
            queryWrapper.like(Student::getName, queryDTO.getName());
        }

        // 学号精确查询
        if (!StringUtils.isEmpty(queryDTO.getStudentNum())) {
            queryWrapper.eq(Student::getStudentNum, queryDTO.getStudentNum());
        }

        // 性别查询
        if (queryDTO.getSex() != null) {
            queryWrapper.eq(Student::getSex, queryDTO.getSex());
        }

        // 班级查询
        if (queryDTO.getClassesId() != null) {
            queryWrapper.eq(Student::getClassesId, queryDTO.getClassesId());
        }

        // 执行查询
        page(page, queryWrapper);

        // 转换为VO
        Page<StudentVO> voPage = new Page<>();
        voPage.setCurrent(page.getCurrent());
        voPage.setSize(page.getSize());
        voPage.setTotal(page.getTotal());
        voPage.setPages(page.getPages());
        voPage.setRecords(studentConverter.toVOList(page.getRecords()));

        return voPage;
    }

    /**
     * 添加学生，包含学号重复检查
     *
     * @param studentDTO 学生信息
     * @return 添加后的学生信息
     * @throws IllegalArgumentException 当学号已存在时抛出
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudentVO addStudent(StudentDTO studentDTO) {
        log.info("执行添加学生：{}", studentDTO);

        // 检查学号是否已存在
        LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Student::getStudentNum, studentDTO.getStudentNum());
        if (count(queryWrapper) > 0) {
            log.warn("学号已存在：{}", studentDTO.getStudentNum());
            throw new IllegalArgumentException("学号已存在，请更换学号");
        }

        // 将DTO转换为实体
        Student student = studentConverter.toEntity(studentDTO);

        // 对密码进行加密
        if (!StringUtils.isEmpty(student.getPassword())) {
            student.setPassword(bCryptUtil.hashPassword(student.getPassword()));
        }

        // 保存学生信息
        boolean result = save(student);
        if (!result) {
            log.error("添加学生失败：{}", studentDTO);
            throw new RuntimeException("添加学生失败");
        }

        // 返回VO
        return studentConverter.toVO(student);
    }

    /**
     * 删除学生（物理删除）
     *
     * @param id 学生ID
     * @return 删除结果，true表示成功，false表示失败
     * @throws IllegalArgumentException 当学生不存在时抛出
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteStudent(Integer id) {
        log.info("执行删除学生，ID：{}", id);

        // 检查学生是否存在
        Student student = getById(id);
        if (student == null) {
            log.warn("学生不存在，ID：{}", id);
            throw new IllegalArgumentException("学生不存在");
        }

        // 删除学生（物理删除）
        return removeById(id);
    }

    /**
     * 分配学生到班级
     *
     * @param id        学生ID
     * @param classesId 班级ID
     * @return 更新后的学生信息
     * @throws IllegalArgumentException 当学生或班级不存在时抛出
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudentVO assignStudentToClass(Integer id, Integer classesId) {
        log.info("执行分配学生到班级，学生ID：{}，班级ID：{}", id, classesId);

        // 检查学生是否存在
        Student student = getById(id);
        if (student == null) {
            log.warn("学生不存在，ID：{}", id);
            throw new IllegalArgumentException("学生不存在");
        }

        // 检查班级是否存在
        if (classesId != null) {
            Classes classes = classesService.getById(classesId);
            if (classes == null) {
                log.warn("班级不存在，ID：{}", classesId);
                throw new IllegalArgumentException("班级不存在");
            }
        }

        // 更新学生的班级ID
        student.setClassesId(classesId);
        boolean result = updateById(student);

        if (!result) {
            log.error("分配学生到班级失败，学生ID：{}，班级ID：{}", id, classesId);
            throw new RuntimeException("分配学生到班级失败");
        }

        // 重新查询并转换为VO
        student = getById(id);
        return studentConverter.toVO(student);
    }

    /**
     * 根据ID获取学生信息
     *
     * @param id 学生ID
     * @return 学生信息
     * @throws IllegalArgumentException 当学生不存在时抛出
     */
    @Override
    public StudentVO getStudentById(Integer id) {
        log.info("执行查询学生详情，ID：{}", id);

        // 查询学生
        Student student = getById(id);
        if (student == null) {
            log.warn("学生不存在，ID：{}", id);
            throw new IllegalArgumentException("学生不存在");
        }

        // 转换为VO并返回
        return studentConverter.toVO(student);
    }

    /**
     * 学生登录
     *
     * @param loginDTO 登录信息
     * @return 登录成功后的学生信息
     * @throws IllegalArgumentException 当学号不存在或密码错误时抛出
     */
    @Override
    public LoginVO login(LoginDTO loginDTO) {
        log.info("执行学生登录，学号：{}", loginDTO.getStudentNum());

        // 根据学号查询学生
        LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Student::getStudentNum, loginDTO.getStudentNum());
        Student student = getOne(queryWrapper);

        // 验证学生是否存在
        if (student == null) {
            log.warn("学号不存在：{}", loginDTO.getStudentNum());
            throw new IllegalArgumentException("学号或密码错误");
        }

        // 验证密码
	    if (!bCryptUtil.checkPassword(loginDTO.getPassword(), student.getPassword())) {
		    log.warn("密码错误，学号：{}", loginDTO.getStudentNum());
		    throw new IllegalArgumentException("学号或密码错误");
	    }

	    log.info("学生登录成功，学号：{}", loginDTO.getStudentNum());

	    // 转换为LoginVO并返回
	    return studentConverter.toLoginVO(student);
    }

	/**
	 * 更新学生信息
	 *
	 * @param id               学生ID
	 * @param studentUpdateDTO 学生更新信息
	 * @return 更新后的学生信息
	 * @throws IllegalArgumentException 当学生不存在时抛出
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public StudentVO updateStudent(Integer id, StudentUpdateDTO studentUpdateDTO) {
		log.info("执行更新学生信息，学生ID：{}，学生信息：{}", id, studentUpdateDTO);

		// 检查学生是否存在
		Student student = getById(id);
		if (student == null) {
			log.warn("学生不存在，ID：{}", id);
			throw new IllegalArgumentException("学生不存在");
		}

		// 检查学号是否已被其他学生使用
		if (!student.getStudentNum().equals(studentUpdateDTO.getStudentNum())) {
			LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.eq(Student::getStudentNum, studentUpdateDTO.getStudentNum())
					.ne(Student::getId, id);
			if (count(queryWrapper) > 0) {
				log.warn("学号已被其他学生使用：{}", studentUpdateDTO.getStudentNum());
				throw new IllegalArgumentException("学号已被其他学生使用，请更换学号");
			}
		}

		// 更新学生信息
		student.setName(studentUpdateDTO.getName());
		student.setStudentNum(studentUpdateDTO.getStudentNum());

		// 更新密码（如果有修改），需要加密
		if (!StringUtils.isEmpty(studentUpdateDTO.getPassword())) {
			student.setPassword(bCryptUtil.hashPassword(studentUpdateDTO.getPassword()));
		}

		// 保存到数据库
		boolean result = updateById(student);
		if (!result) {
			log.error("更新学生信息失败，学生ID：{}", id);
			throw new RuntimeException("更新学生信息失败");
		}

		// 返回更新后的学生信息
		student = getById(id);
		return studentConverter.toVO(student);
	}
}




